/*
 * Copyright 2016 jeasonlzy(廖子尧)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lzy.demo;

import com.google.gson.Gson;
import com.lzy.demo.utils.ImageUtil;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.adapter.Call;
import com.lzy.okgo.callback.BitmapCallback;
import com.lzy.okgo.callback.StringCallback;
import com.lzy.okgo.convert.FileConvert;
import com.lzy.okgo.convert.StringConvert;
import com.lzy.okgo.db.DownloadManager;
import com.lzy.okgo.model.Progress;
import com.lzy.okgo.model.Response;
import com.lzy.okgo.request.GetRequest;
import com.lzy.okgo.utils.HttpUtils;
import com.lzy.okgo.utils.OkLogger;
import com.lzy.okrx2.utils.HosSchedulers;
import com.lzy.okrx2.adapter.ObservableResponse;
import com.lzy.okserver.OkDownload;
import com.lzy.okserver.download.DownloadListener;
import com.lzy.okserver.download.DownloadTask;
import io.reactivex.Observer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.ProgressBar;
import ohos.agp.components.Text;
import ohos.media.image.PixelMap;
import ohos.utils.zson.ZSONObject;
import okhttp3.Headers;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 详情类
 */
public class BaseDetailsAbility extends Ability implements Component.ClickedListener {
    private Text requestState;
    private Text requestHeaders;
    private Text responseData;
    private Text responseHeader;
    private Image downImage;
    private int actionType;
    private File downFile;
    private ProgressBar progressBar;
    private static final String SMILE_PICTURE = "https://media.w3.org/2010/05/sintel/trailer.mp4";
    private Button btnGet;
    private Button btnPost;
    private Button btnPut;
    private Button btnDelete;
    private Button btnPatch;
    private Button btnDownload;
    private Button btnUpload;
    private Button syncGet;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_layout_base_details);

        if (findComponentById(ResourceTable.Id_get) instanceof Button) {
            btnGet = (Button) findComponentById(ResourceTable.Id_get);
        }

        if (findComponentById(ResourceTable.Id_post) instanceof Button) {
            btnPost = (Button) findComponentById(ResourceTable.Id_post);
        }
        if (findComponentById(ResourceTable.Id_put) instanceof Button) {
            btnPut = (Button) findComponentById(ResourceTable.Id_put);
        }
        if (findComponentById(ResourceTable.Id_delete) instanceof Button) {
            btnDelete = (Button) findComponentById(ResourceTable.Id_delete);
        }
        if (findComponentById(ResourceTable.Id_patch) instanceof Button) {
            btnPatch = (Button) findComponentById(ResourceTable.Id_patch);
        }
        if (findComponentById(ResourceTable.Id_download) instanceof Button) {
            btnDownload = (Button) findComponentById(ResourceTable.Id_download);
        }
        if (findComponentById(ResourceTable.Id_uploadJson) instanceof Button) {
            btnUpload = (Button) findComponentById(ResourceTable.Id_uploadJson);
        }
        if (findComponentById(ResourceTable.Id_syncGet) instanceof Button) {
            syncGet = (Button) findComponentById(ResourceTable.Id_syncGet);
        }
        if (findComponentById(ResourceTable.Id_progressBar1) instanceof ProgressBar) {
            progressBar = (ProgressBar) findComponentById(ResourceTable.Id_progressBar1);
        }

        if (findComponentById(ResourceTable.Id_requestState) instanceof Text) {
            requestState = (Text) findComponentById(ResourceTable.Id_requestState);
        }
        if (findComponentById(ResourceTable.Id_requestHeader) instanceof Text) {
            requestHeaders = (Text) findComponentById(ResourceTable.Id_requestHeader);
        }
        if (findComponentById(ResourceTable.Id_responseHeader) instanceof Text) {
            responseHeader = (Text) findComponentById(ResourceTable.Id_responseHeader);
        }
        if (findComponentById(ResourceTable.Id_responseData) instanceof Text) {
            responseData = (Text) findComponentById(ResourceTable.Id_responseData);
        }
        if (findComponentById(ResourceTable.Id_DownImage) instanceof Image) {
            downImage = (Image) findComponentById(ResourceTable.Id_DownImage);
        }
        createInit();
        initActionType();
    }

    private void createInit() {
        actionType = getIntent().getIntParam("ActionType", 0);
        btnGet.setClickedListener(this);
        btnPost.setClickedListener(this);
        btnPut.setClickedListener(this);
        btnDelete.setClickedListener(this);
        btnPatch.setClickedListener(this);
        btnDownload.setClickedListener(this);
        btnUpload.setClickedListener(this);
        syncGet.setClickedListener(this);
        progressBar.setMaxValue(100);
        progressBar.setMinValue(0);
        progressBar.setProgressValue(0);
    }

    private void initActionType() {
        switch (actionType) {
            case 0:

                break;
            case 1:
                btnDelete.setText("Rx2基本请求");
                btnGet.setText("Rx2上传string");
                btnPost.setText("Rx2上传json");
                syncGet.setText("Rx2下载文件");

                btnPut.setVisibility(Component.HIDE);
                btnPatch.setVisibility(Component.HIDE);
                btnDownload.setVisibility(Component.HIDE);
                btnUpload.setVisibility(Component.HIDE);
                break;

            case 2:
                btnDelete.setText("OkServer下载文件");

                progressBar.setVisibility(Component.VISIBLE);

                btnGet.setVisibility(Component.HIDE);
                btnPost.setVisibility(Component.HIDE);
                syncGet.setVisibility(Component.HIDE);
                btnPut.setVisibility(Component.HIDE);
                btnPatch.setVisibility(Component.HIDE);
                btnDownload.setVisibility(Component.HIDE);
                btnUpload.setVisibility(Component.HIDE);
                break;
        }
    }

    private void switchActionType(int actionType, int resId) {
        switch (actionType) {
            case 0:
                initOkGo(resId);
                break;
            case 1:
                initOkRx2(resId);
                break;
            case 2:
                initOkDownload(resId);
                break;
        }
    }

    private void getMethod() {
        OkGo.<String>get("https://httpbin.org/get")
                .tag(this)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        OkLogger.e("GET响应:---" + response.body());
                        handleResponse(response);
                    }
                });
    }

    private void postMethod() {
        // 测试POST 请求
        OkGo.<String>post("https://httpbin.org/post")
                .params("username", "zhouxin8357")
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        OkLogger.e("POST请求响应:---" + response.body());
                        handleResponse(response);
                    }
                });
    }

    private void deleteMethod() {
        // 测试DELETE 请求
        OkGo.<String>delete("https://httpbin.org/delete")
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        OkLogger.e("DELETE请求响应:---" + response.body());
                        handleResponse(response);
                    }
                });
    }

    private void putMethod() {
        // 测试PUT请求
        OkGo.<String>put("https://httpbin.org/put")
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        OkLogger.e("PUT请求响应:---" + response.body());
                        handleResponse(response);
                    }
                });
    }

    private void patchMethod() {
        // 测试PATCH请求
        OkGo.<String>patch("https://httpbin.org/patch")
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        OkLogger.e("PATCH请求响应:---" + response.body());
                        handleResponse(response);
                    }
                });
    }

    private void downloadMethod() {
        // 测试DOWNLOAD请求
        OkGo.<PixelMap>get("https://httpbin.org/image/webp")
                .tag(this)
                .headers("header1", "headerValue1")
                .params("param1", "paramValue1")
                .execute(new BitmapCallback() {
                    @Override
                    public void onSuccess(Response<PixelMap> response) {
                        downImage.setPixelMap(response.body());
                        handleResponse(response);
                    }
                });
    }

    private void uploadJsonMethod() {
        Map<String, Object> params = new HashMap<>();
        params.put("key1", "value1");
        params.put("key2", "这里是需要提交的json格式数据");
        params.put("key3", "也可以使用三方工具将对象转成json字符串");
        params.put("key4", "其实你怎么高兴怎么写都行");
        ZSONObject jsonObject = new ZSONObject(params);
        OkGo.<String>post("https://httpbin.org/post")
                .tag(this)
                .headers("header1", "headerValue1")
                .upJson(jsonObject)
                .execute(new StringCallback() {
                    @Override
                    public void onSuccess(Response<String> response) {
                        OkLogger.e("upJson请求响应:---" + response.body());
                        handleResponse(response);
                    }
                });
    }

    private void syncGetMethod() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 同步会阻塞主线程，必须开新线程发起请求
                    Call<String> call = OkGo.<String>get("https://httpbin.org/get")
                            .tag(this)
                            .headers("header1", "headerValue1")
                            .params("param1", "syncGet")
                            .converter(new StringConvert())
                            .adapt();
                    Response<String> response = call.execute();

                    HttpUtils.runOnUiThread(() -> {
                        OkLogger.e("同步请求响应:---" + response.body());
                        handleResponse(response);
                    });
                } catch (Exception e) {
                    OkLogger.e(e.getMessage());
                }
            }
        }).start();
    }

    private void initOkGo(int resId) {
        switch (resId) {
            case ResourceTable.Id_get:
                getMethod();
                break;
            case ResourceTable.Id_post:
                postMethod();
                break;
            case ResourceTable.Id_delete:
                deleteMethod();
                break;
            case ResourceTable.Id_put:
                putMethod();
                break;
            case ResourceTable.Id_patch:
                patchMethod();
                break;
            case ResourceTable.Id_download:
                downloadMethod();
                break;
            case ResourceTable.Id_uploadJson:
                uploadJsonMethod();
                break;
            case ResourceTable.Id_syncGet:
                syncGetMethod();
                break;
        }

    }

    private void rx2PostMethod() {
        OkGo.<String>post("https://httpbin.org/post")
                .headers("aaa", "111")
                .upString("19190520")
                .converter(new StringConvert())
                .adapt(new ObservableResponse<String>())
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {

                    }
                })
                .observeOn(HosSchedulers.mainThread())
                .subscribe(new Observer<Response<String>>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(Response<String> response) {
                        OkLogger.e("Rx2上传string请求响应:---" + response.body());
                        handleResponse(response);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        OkLogger.e(throwable.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void rx2PostParamsMethod() {
        Map<String, Object> params = new HashMap<>();
        params.put("key1", "83578357");
        params.put("key2", "这里是需要提交的json格式数据");
        params.put("key3", "也可以使用三方工具将对象转成json字符串");
        params.put("key4", "其实你怎么高兴怎么写都行");
        ZSONObject jsonObject = new ZSONObject(params);
        OkGo.<String>post("https://httpbin.org/post")
                .headers("aaa", "111")
                .upJson(jsonObject)
                .converter(new StringConvert())
                .adapt(new ObservableResponse<String>())
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {

                    }
                })
                .observeOn(HosSchedulers.mainThread())
                .subscribe(new Observer<Response<String>>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(Response<String> response) {
                        OkLogger.e("Rx2上传json请求响应:---" + response.body());
                        handleResponse(response);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        handleError();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void rx2deleteMethod() {
        OkGo.<String>post("https://httpbin.org/post")
                .headers("aaa", "111")
                .params("bbb", "007")
                .converter(new StringConvert())
                .adapt(new ObservableResponse<String>())
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {

                    }
                })
                .observeOn(HosSchedulers.mainThread())
                .subscribe(new Observer<Response<String>>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(Response<String> response) {
                        OkLogger.e("Rx2基本请求响应:---" + response.body());
                        handleResponse(response);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        handleError();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void rx2SyncGetMethod() {
        // 使用okrx直接下，下载进度封装比较麻烦,推荐使用回调方式
        OkGo.<File>get("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603365041957&di=4330bd6c4aa2c27cf08f51e7019983a7&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201208%2F18%2F20120818173057_nNFRz.png")
                .headers("aaa", "111")
                .params("bbb", "222")
                .converter(new FileConvert())
                .adapt(new ObservableResponse<File>())
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {

                    }
                })
                .observeOn(HosSchedulers.mainThread())
                .subscribe(new Observer<Response<File>>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(Response<File> response) {
                        downImage.setPixelMap(ImageUtil.getPixelMapByFile(response.body()));
                        downFile = response.body();
                        OkLogger.e("Rx2下载图片响应:---" + response.body().getAbsolutePath());
                        handleResponse(response);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        OkLogger.e("Rx2下载图片响应:---" + throwable.getMessage());
                        handleError();
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void initOkRx2(int resId) {
        switch (resId) {
            case ResourceTable.Id_get:
                rx2PostMethod();
                break;
            case ResourceTable.Id_post:
                rx2PostParamsMethod();
                break;
            case ResourceTable.Id_delete:
                rx2deleteMethod();
                break;
            case ResourceTable.Id_syncGet:
                rx2SyncGetMethod();
                break;
            case ResourceTable.Id_put:
                break;
        }
    }

    private void initOkDownload(int resId) {
        if (resId == ResourceTable.Id_delete) {
            // 这里只是演示，表示请求可以传参，怎么传都行，和okgo使用方法一样
            GetRequest<File> request = OkGo.<File>get(SMILE_PICTURE);
            // 这里第一个参数是tag，代表下载任务的唯一标识，传任意字符串都行，需要保证唯一,我这里用url作为了tag
            DownloadTask task = OkDownload.request(SMILE_PICTURE, request)
                    .priority(100)
                    .save()
                    .register(new DownloadListener(SMILE_PICTURE) {
                        @Override
                        public void onStart(Progress progress) {

                        }

                        @Override
                        public void onProgress(Progress progress) {
                            OkLogger.e("onProgress: " + progress);
                            progressBar.setProgressValue((int) (1.0f * progress.currentSize / progress.totalSize * 100));
                        }

                        @Override
                        public void onError(Progress progress) {
                        }

                        @Override
                        public void onFinish(File file, Progress progress) {
                            OkLogger.e("onFinish: " + progress);
                            try {
                                responseData.setText(file.getCanonicalPath());
                            } catch (IOException e) {
                                OkLogger.d(e.getMessage());
                            }
                        }

                        @Override
                        public void onRemove(Progress progress) {

                        }
                    });

            Progress progress = DownloadManager.getInstance().get(SMILE_PICTURE);
            if (progress.status == Progress.LOADING) {
                task.pause();
            } else if ((progress.status == Progress.PAUSE) || (progress.status == Progress.NONE)) {
                task.start();
            }
        }
    }

    @Override
    public void onClick(Component component) {
        switchActionType(actionType, component.getId());
    }


    private <T> void handleResponse(Response<T> response) {
        StringBuilder sb;
        okhttp3.Call call = response.getRawCall();
        if (call != null) {
            requestState.setText("请求成功  请求方式：" + call.request().method() + "url：" + call.request().url());

            Headers requestHeadersString = call.request().headers();
            Set<String> requestNames = requestHeadersString.names();
            sb = new StringBuilder();
            for (String name : requestNames) {
                sb.append(name).append(" ： ").append(requestHeadersString.get(name)).append("");
            }
            requestHeaders.setText(sb.toString());
        } else {
            requestState.setText("--");
            requestHeaders.setText("--");
        }
        initResponseData(response);
        initResponseHeader(response);
    }

    private <T> void initResponseData(Response<T> response) {
        StringBuilder sb;
        T body = response.body();
        if (body == null) {
            responseData.setText("--");
        } else {
            if (body instanceof String) {
                responseData.setText((String) body);
            } else if (body instanceof List) {
                sb = new StringBuilder();
                List list = (List) body;
                for (Object obj : list) {
                    sb.append(obj.toString()).append("");
                }
                responseData.setText(sb.toString());
            } else if (body instanceof Set) {
                sb = new StringBuilder();
                Set set = (Set) body;
                for (Object obj : set) {
                    sb.append(obj.toString()).append("");
                }
                responseData.setText(sb.toString());
            } else if (body instanceof Map) {
                sb = new StringBuilder();
                Map map = (Map) body;
                Set keySet = map.keySet();
                for (Object key : keySet) {
                    sb.append(key.toString()).append(" ： ").append(map.get(key)).append("");
                }
                responseData.setText(sb.toString());
            } else if (body instanceof File) {
                File file = (File) body;
                try {
                    responseData.setText("数据内容即为文件内容下载文件路径：" + file.getCanonicalPath());
                } catch (IOException e) {
                    OkLogger.d(e.getMessage());
                }
            } else if (body instanceof PixelMap) {
                responseData.setText("图片的内容即为数据");
            } else {
                responseData.setText(new Gson().toJson(body));
            }
        }
    }

    private void initResponseHeader(Response response) {
        okhttp3.Response rawResponse = response.getRawResponse();
        if (rawResponse != null) {
            Headers responseHeadersString = rawResponse.headers();
            Set<String> names = responseHeadersString.names();
            StringBuilder sb = new StringBuilder();
            sb.append("url ： ").append(rawResponse.request().url()).append("");
            sb.append("stateCode ： ").append(rawResponse.code()).append("");
            for (String name : names) {
                sb.append(name).append(" ： ").append(responseHeadersString.get(name)).append("");
            }
            responseHeader.setText(sb.toString());
        } else {
            responseHeader.setText("--");
        }
    }

    private <T> void handleError() {
        Response<T> response = new Response<>();
        handleResponse(response);
    }

    private <T> void handleError(Response<T> response) {
        if (response == null) {
            return;
        }
        if (response.getException() != null) {
            response.getException().printStackTrace();
        }
        StringBuilder sb;
        okhttp3.Call call = response.getRawCall();
        if (call != null) {
            requestState.setText("请求失败  请求方式：" + call.request().method() + "" + "url：" + call.request().url());

            Headers requestHeadersString = call.request().headers();
            Set<String> requestNames = requestHeadersString.names();
            sb = new StringBuilder();
            for (String name : requestNames) {
                sb.append(name).append(" ： ").append(requestHeadersString.get(name)).append("");
            }
            requestHeaders.setText(sb.toString());
        } else {
            requestState.setText("--");
            requestHeaders.setText("--");
        }

        responseData.setText("--");
        okhttp3.Response rawResponse = response.getRawResponse();
        if (rawResponse != null) {
            Headers responseHeadersString = rawResponse.headers();
            Set<String> names = responseHeadersString.names();
            sb = new StringBuilder();
            sb.append("stateCode ： ").append(rawResponse.code()).append("");
            for (String name : names) {
                sb.append(name).append(" ： ").append(responseHeadersString.get(name)).append("");
            }
            responseHeader.setText(sb.toString());
        } else {
            responseHeader.setText("--");
        }
    }
}

